import axios from 'axios';
import config from '../config/api';
import { getToken, reLogin } from './auth';

let { HTTP_REQUEST_URL, HEADER, TOKEN_FORMAT, CACHE_TOKEN, TOKENNAME } = config;

// 缓存存储格式：get和post请求数据单独分为两个对象，分别存储url+params的拼接结果作为key值，缓存值作为value
const cache = { get: {}, post: {} };

/*
 * 对象key值排序方法，保证不同顺序的key值对比有效
 */

// 创建一个 axios 实例
const instance = axios.create({
  baseURL: HTTP_REQUEST_URL, // 公共的接口地址
  timeout: 50000, // 请求超时时间设置
  withCredentials: true, //跨域时使用凭证，默认带上cookies
});

// 请求拦截器，config 是发送请求的参数信息
instance.interceptors.request.use(
  (config) => {
    // 是否请求需要带上 token
    // @ts-ignore
    if (!config.noToken)
      config.headers[TOKENNAME] = TOKEN_FORMAT(getToken(CACHE_TOKEN));
    return config;
  },
  // 请求拦截的错误回调
  (error) => {
    console.log(error);
    return Promise.reject(error);
  },
);

// 响应拦截器，response为响应的结构组织，包括data，headers，status，statusText，config，request
instance.interceptors.response.use(
  (response) => {
    // 后台返回数据
    const data = response.data;
    // 这个状态码和提示信息是和后端约定的
    const { code, msg } = data;
    // 根据 code 进行判断，与后端约定某些状态该返回什么数据
    switch (code) {
      // 如果没有 code，可能后端返回的数据不是json类型，直接返回响应结构
      case undefined:
        return response;
      //code === 200 代表没有错误，这里的状态 200 是与后端协商的成功状态码
      case 200:
        return data;
      // 举例：token已过期的code报错，需要返回登录页重新登录！与后端约定20003为token过期状态！
      case 20003:
        console.error(`token已过期，请重新登录`);
        // 跳转登录页，清除登录信息！
        break;
      // 其他 code，抛出错误提示信息
      default:
        console.error(`[ code: ${code}] ${msg}`);
        return data;
    }
  },
  // 响应拦截的报错信息，协议报错
  (error) => {
    if (error && error.response) {
      switch (error.response.status) {
        case 400:
          error.message = '请求错误';
          break;
        case 401:
          (error.message = '未授权，请登录'), reLogin();
          break;
        case 403:
          error.message = '拒绝访问';
          break;
        case 404:
          error.message = `请求地址错误: ${error.response.config.url}`;
          break;
        case 408:
          error.message = '请求超时';
          break;
        case 500:
          error.message = '服务器内部错误';
          break;
        case 501:
          error.message = '服务未实现';
          break;
        case 502:
          error.message = '网关错误';
          break;
        case 503:
          error.message = '服务不可用';
          break;
        case 504:
          error.message = '网关超时';
          break;
        case 505:
          error.message = 'HTTP版本不受支持';
          break;
        default:
          error.message = '其他未知错误';
          break;
      }
    }
    console.error(error);
    return Promise.reject(error);
  },
);
// 导出
export { instance };
